package com.fessc.develop.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fessc.develop.base.Result;
import com.fessc.develop.entity.comvo.CallApiBackVo;
import com.fessc.develop.entity.comvo.SysHeadVo;
import com.fessc.develop.entity.dbvo.TOrgUrlManage;
import com.fessc.develop.exception.BusinessException;
import com.fessc.develop.handler.SignHandler;
import com.fessc.develop.model.enums.EnumJsonProperty;
import com.fessc.develop.model.enums.EnumResultType;
import com.fessc.develop.model.enums.EnumServiceCode;
import com.fessc.develop.handler.processor.request.IBaseService;
import com.fessc.develop.service.interfaces.ITOrgUrlManageService;
import com.fessc.develop.utils.BusiUtil;
import com.fessc.develop.utils.ExceptionUtil;
import com.fessc.develop.utils.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ComCallApiBaseService {

    @Resource
    List<IBaseService> baseServices;

    @Resource
    private ITOrgUrlManageService orgUrlManageService;

    @Resource
    private SignHandler signHandler;

    @Resource
    private CallApiBackVo callApiBackVo;

    private Map<String, IBaseService> serviceMap;


    @PostConstruct
    void init() {
        if (BusiUtil.isNotNull(baseServices)) {
            serviceMap = baseServices.stream().collect(Collectors.toMap(IBaseService::getServiceCode, p -> p, (v1, v2) -> v1));
        } else {
            serviceMap = new HashMap<>();
        }
    }

    public Result process(String requestBody) {
        Result result;
        TOrgUrlManage orgUrlManage = new TOrgUrlManage();
        try {
            // 获取报文头，进行检查、分发
            JSONObject request = JSON.parseObject(requestBody);
            log.info("comcallapi请求报文密文：" + request.toJSONString());

            //获取请求报文head
            SysHeadVo sysHead = check(request);

            //根据请求报文head，获取请求市场交易中心编码或者银行编号，查询URL配置表得到对应的公钥，再根据公钥加解密报文
            orgUrlManage = getOrgUrlManage(sysHead);

            //报文体用自己的私钥解密
            String body = signHandler.decrypt(request.getString(EnumJsonProperty.REQ_BODY.toString()));
            request.put(EnumJsonProperty.REQ_BODY.toString(), JSON.parseObject(body));
            log.info("comcallapi请求接口编号：" + sysHead.getServiceCode());
            log.info("comcallapi请求解密明文：" + request.toJSONString());

            IBaseService baseService = serviceMap.get(sysHead.getServiceCode());
            if (BusiUtil.isNull(baseService)) {
                throw ExceptionUtil.businessException("EE4011");
            }
            result = baseService.process(request);
            //返回报文用对应机构的公钥加密返回
            log.info("comcallapi返回报文明文：" + JSON.toJSONString(result));
            if (BusiUtil.isNotNull(result.getData())) {
                result.setData(signHandler.encrypt(JSON.toJSONString(result.getData()), orgUrlManage.getPubCert()));
            }
        } catch (BusinessException e) {
            log.info("交易失败：" + e.getMessage());
            log.error(e.getResult().getMsg(), e);
            result = e.getResult();
            callApiBackVo.setReturnCode(e.getResult().getStatusCode());
            callApiBackVo.setReturnMessage(e.getResult().getMsg());
            result.setData(callApiBackVo);
            log.info("交易失败返回报文：" + JSON.toJSONString(result));
            result.setData(signHandler.encrypt(JSON.toJSONString(callApiBackVo), orgUrlManage.getPubCert()));
        } catch (Throwable e) {
            log.info("系统异常：" + e.getMessage());
            log.error(e.getMessage(), e);
            result = new Result(EnumResultType.FAIL.getStatusCode(), EnumResultType.FAIL.getMsg());
            callApiBackVo.setReturnCode(EnumResultType.FAIL.getStatusCode());
            callApiBackVo.setReturnMessage(EnumResultType.FAIL.getMsg());
            result.setData(callApiBackVo);
            log.info("系统异常返回报文：" + JSON.toJSONString(result));
            result.setData(signHandler.encrypt(JSON.toJSONString(callApiBackVo), orgUrlManage.getPubCert()));
        }
        log.info("comcallapi返回报文密文：" + JSON.toJSONString(result));
        return result;

    }

    public SysHeadVo check(JSONObject request) {
        //检查检查报文是否为空
        SysHeadVo sysHead = new SysHeadVo();
        if (BusiUtil.isNull(request)) {
            throw ExceptionUtil.businessException("EE1012");
        }
        JSONObject head = request.getJSONObject(EnumJsonProperty.REQ_SYS_HEAD.toString());
        String body = request.getString(EnumJsonProperty.REQ_BODY.toString());
        //检查报文head是否为空
        if (BusiUtil.isNull(head)) {
            throw ExceptionUtil.businessException("EE1013");
        }
        //检查报文body是否为空
        if (BusiUtil.isNull(body) || ObjectUtil.isAllFieldNull(body)) {
            throw ExceptionUtil.businessException("EE1014");
        }
        sysHead = JSON.parseObject(head.toJSONString(), SysHeadVo.class);
        //检查报文head字段是否为空
        if (ObjectUtil.isAllFieldNull(sysHead)) {
            throw ExceptionUtil.businessException("EE1013");
        }
        //市场交易平台请求接口
        if (BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.PLAT_MP0003.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.PLAT_MP0004.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.PLAT_MP0005.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.PLAT_MP0006.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.PLAT_MP0000.toString())) {
            if (BusiUtil.isNull(sysHead.getOrgCode())) {
                throw ExceptionUtil.businessException("EE1002");
            } else {
                return sysHead;
            }
        } else if (BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0001.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0002.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0003.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0004.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0005.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0006.toString()) ||
                BusiUtil.isEquals(sysHead.getServiceCode(), EnumServiceCode.COM_BS0000.toString())) {
            if (BusiUtil.isNull(sysHead.getBankId())) {
                throw ExceptionUtil.businessException("EE1017");
            } else {
                return sysHead;
            }
        } else {
            throw ExceptionUtil.businessException("EE4011");
        }
    }

    public TOrgUrlManage getOrgUrlManage(SysHeadVo sysHead) {
        // 查询请求对应的公钥ID，银行请求用BANK_ID查询，市场交易平台用ORG_CODE查询
        List<TOrgUrlManage> orgUrlManage = new ArrayList<TOrgUrlManage>();
        if (sysHead.getServiceCode().contains("MP")) {
            // 市场交易平台请求报文
            log.info("请求市场交易平台: " + sysHead.getOrgCode());
            orgUrlManage = orgUrlManageService.getPubCertByOrgCodeAndKey(sysHead.getOrgCode());
        } else if (sysHead.getServiceCode().contains("BS")) {
            // 银行请求报文
            log.info("请求银行编号: " + sysHead.getBankId());
            orgUrlManage = orgUrlManageService.getPubCertByOrgCodeAndKey(sysHead.getBankId());
        } else {
            throw ExceptionUtil.businessException("EE1017");
        }
        // 判断配置url是否存在，该配置表保存有对应的公钥ID，返回报文使用该公钥进行加密
        if (BusiUtil.isNull(orgUrlManage) || orgUrlManage.isEmpty()) {
            throw ExceptionUtil.businessException("EE1018");
        }
        //各个接口配置的公钥相同，取其一即可
        return orgUrlManage.get(0);
    }

}
